package com.bdilab.iot.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.extension.api.R;
import com.bdilab.iot.dao.PermissionMapper;
import com.bdilab.iot.dao.RoleMapper;
import com.bdilab.iot.dao.RolePermissionRelationMapper;
import com.bdilab.iot.dto.roleDto.CreateRoleDto;
import com.bdilab.iot.dto.roleDto.RoleWithPermission;
import com.bdilab.iot.dto.roleDto.UpdateRoleDto;
import com.bdilab.iot.exception.NotFoundException;
import com.bdilab.iot.exception.ServerException;
import com.bdilab.iot.model.Permission;
import com.bdilab.iot.model.Role;
import com.bdilab.iot.model.RolePermissionRelation;
import com.bdilab.iot.service.RoleService;

import com.bdilab.iot.utils.ParsePermissionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.sql.rowset.serial.SerialException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author WangNing
 * @version 1.0
 * @date 2020/8/1 17:19
 */
@Service
@Slf4j
public class RoleServiceImpl implements RoleService {

    @Resource
    RoleMapper roleMapper;

    @Resource
    PermissionMapper permissionMapper;


    @Resource
    RolePermissionRelationMapper rolePermissionRelationMapper;

    @Override
    public List<Role> getAllRole() {
        return roleMapper.getAllRole();
    }

    /**
     * 创建角色
     * @param createRoleDto
     * @return
     */
    @Override
    @Transactional
    public synchronized Role createRole(CreateRoleDto createRoleDto) {
        if(StringUtils.isEmpty(createRoleDto.getRoleName())){
            throw new ServerException("角色名不能为空");
        }
        int count = roleMapper.countRoleName(createRoleDto.getRoleName());
        if(count > 0)
            throw new ServerException("角色名已存在");

        List<Long> permissionIDs = permissionMapper.getAllPermissionID();

        if(createRoleDto.getPermissions().stream().distinct().count()>0)
            throw new ServerException("用户绑定重复的权限");

        createRoleDto.getPermissions().forEach(p->{

            if(!permissionIDs.contains(p)){
                throw new ServerException("角色绑定系统不存在的权限");
            }

        });
        Role role = new Role();
        role.setName(createRoleDto.getRoleName());
        role.setDescription(createRoleDto.getDescription());
        role.setCreateTime(new Date());
        role.setUpdateTime(new Date());
        int result = roleMapper.insert(role);
        if(result < 0){

            log.error("创建角色时出现未知错误:{}", createRoleDto.getRoleName());
            throw new ServerException("创建角色时出现未知错误");

        }

        List<RolePermissionRelation> relations = new ArrayList<>();
        createRoleDto.getPermissions().forEach(p ->{

            RolePermissionRelation rolePermissionRelation = new RolePermissionRelation();
            rolePermissionRelation.setRoleId(role.getId());
            rolePermissionRelation.setPermissionId(p);
            relations.add(rolePermissionRelation);

        });

        result = rolePermissionRelationMapper.insertBatch(relations);

        if(result < 0){

            log.error("创建角色权限对应表时出现未知错误:{}", relations);
            throw new ServerException("创建角色权限对应表时出现未知错误");

        }

        return role;
    }


    /**
     * 获取单个角色
     * @param id
     * @return
     */
    @Override
    public RoleWithPermission getRole(Long id) {
        Role role =  roleMapper.selectById(id);
        if(role == null)
            throw  new NotFoundException("角色不存在");
        List<Permission> permissions = permissionMapper.getByRoleId(role.getId());
        RoleWithPermission roleWithPermission = new RoleWithPermission();
        BeanUtils.copyProperties(role, roleWithPermission);
        roleWithPermission.setPermissions(ParsePermissionUtils.parsePermission(permissions));
        return roleWithPermission;
    }

    /**
     * 删除角色
     * @param id
     */
    @Override
    @Transactional
    public void deleteRole(Long id) {

        int result = roleMapper.deleteById(id);

        if(result <= 0)
            throw new NotFoundException("未找到该角色");

        rolePermissionRelationMapper.deleteByRoleId(id);

    }

    /**
     * 更新角色
     * @param updateRoleDto
     * @return
     */
    @Override
    @Transactional
    public Role updateRole(UpdateRoleDto updateRoleDto, Long id) {
        if(!StringUtils.isEmpty(updateRoleDto.getRoleName())){
            int count = roleMapper.countRoleName(updateRoleDto.getRoleName());
            if(count > 0)
                throw new ServerException("角色名已存在");

        }
        List<Long> permissionIDs = permissionMapper.getAllPermissionID();
        if(updateRoleDto.getPermissions()!=null){

            if(updateRoleDto.getPermissions().size() == 0)
                throw new ServerException("角色必须指定至少一个权限");

            if(updateRoleDto.getPermissions().stream().distinct().count()>0)
                throw new ServerException("用户绑定重复的权限");

            updateRoleDto.getPermissions().forEach(p->{

                if(!permissionIDs.contains(p)){
                    throw new ServerException("角色绑定系统不存在的权限");
                }

            });

        }


        Role role = new Role();
        role.setId(id);
        role.setDescription(updateRoleDto.getDescription());
        role.setName(updateRoleDto.getRoleName());
        role.setUpdateTime(new Date());
        roleMapper.updateRole(role);
        rolePermissionRelationMapper.deleteByRoleId(id);

        List<RolePermissionRelation> relations = new ArrayList<>();
        updateRoleDto.getPermissions().forEach(p ->{

            RolePermissionRelation rolePermissionRelation = new RolePermissionRelation();
            rolePermissionRelation.setRoleId(role.getId());
            rolePermissionRelation.setPermissionId(p);
            relations.add(rolePermissionRelation);

        });

        int result = rolePermissionRelationMapper.insertBatch(relations);

        if(result < 0){

            log.error("更新角色权限对应表时出现未知错误:{}", relations);
            throw new ServerException("更新角色权限对应表时出现未知错误");

        }

        return role;

    }

}
